home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / lapb.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  22KB  |  854 lines

  1. /* Link Access Procedures Balanced (LAPB), the upper sublayer of
  2.  * AX.25 Level 2.
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  * 92/02/07 WG7J
  6.  * Modified to drop ax.25 route records in cases where routes
  7.  * were added by the connections. Inspired by K4TQL
  8.  */
  9. #include "global.h"
  10. #include "config.h"
  11. #ifdef AX25
  12. #include "mbuf.h"
  13. #include "timer.h"
  14. #include "ax25.h"
  15. #include "lapb.h"
  16. #include "ip.h"
  17. #include "netrom.h"
  18.  
  19. /* This forces data sent by jumpstarting a mailbox connect to
  20.  * resend the header etc. when the first UA reply is missed, and
  21.  * a second SABM is received for the same connection
  22.  * added by Ron Murray VK6ZJM, Murray_RJ@cc.curtin.edu.au
  23.  */
  24. #define SABM_HOLDOFF
  25.  
  26. static void handleit __ARGS((struct ax25_cb *axp,int pid,struct mbuf *bp));
  27. static void procdata __ARGS((struct ax25_cb *axp,struct mbuf *bp));
  28. static int ackours __ARGS((struct ax25_cb *axp,int16 n));
  29. static void clr_ex __ARGS((struct ax25_cb *axp));
  30. static void enq_resp __ARGS((struct ax25_cb *axp));
  31. static void inv_rex __ARGS((struct ax25_cb *axp));
  32. static void drop_axr __ARGS((struct ax25_cb *axp));
  33.  
  34. /*needed for mailbox jumpstart - WG7J */
  35. #ifdef MAILBOX
  36. #ifdef NETROM
  37. extern struct nrnbr_tab *find_nrnbr __ARGS((char *, struct iface *));
  38. #endif
  39. extern int Mbjumpstart;
  40. extern struct no_js *Exclude;
  41. #endif
  42.  
  43. /*If we have an AX.25 AUTO route record, drop it.*/
  44. static void
  45. drop_axr(axp)
  46. struct ax25_cb *axp;
  47. {
  48.     struct ax_route *axr;
  49.  
  50.     axr = ax_lookup(axp->remote,axp->iface);
  51.     if(axr != NULLAXR && axr->type != AX_LOCAL)
  52.     ax_drop(axp->remote,axp->iface);
  53.  
  54. }
  55.  
  56. /* Process incoming frames */
  57. int
  58. lapb_input(axp,cmdrsp,bp)
  59. struct ax25_cb *axp;            /* Link control structure */
  60. int cmdrsp;                     /* Command/response flag */
  61. struct mbuf *bp;                /* Rest of frame, starting with ctl */
  62. {
  63.     int control;
  64.     int class;              /* General class (I/S/U) of frame */
  65.     int16 type;             /* Specific type (I/RR/RNR/etc) of frame */
  66.     char pf;                /* extracted poll/final bit */
  67.     char poll = 0;
  68.     char final = 0;
  69.     int16 nr;               /* ACK number of incoming frame */
  70.     int16 ns;               /* Seq number of incoming frame */
  71.     int16 tmp;
  72. #ifdef MAILBOX
  73.     struct no_js *ep;   /*scan the 'exclude-calls' list */
  74. #endif
  75.  
  76.     if(bp == NULLBUF || axp == NULLAX25){
  77.         free_p(bp);
  78.         return -1;
  79.     }
  80.  
  81.     /* Extract the various parts of the control field for easy use */
  82.     if((control = PULLCHAR(&bp)) == -1){
  83.         free_p(bp);     /* Probably not necessary */
  84.         return -1;
  85.     }
  86.     type = ftype(control);
  87.     class = type & 0x3;
  88.     pf = control & PF;
  89.     /* Check for polls and finals */
  90.     if(pf){
  91.         switch(cmdrsp){
  92.         case LAPB_COMMAND:
  93.             poll = YES;
  94.             break;
  95.         case LAPB_RESPONSE:
  96.             final = YES;
  97.             break;
  98.         }
  99.     }
  100.     /* Extract sequence numbers, if present */
  101. #ifdef __GNUC__
  102.     ns = 0;            /* silence warning */
  103. #endif
  104.     switch(class){
  105.     case I:
  106.     case I+2:
  107.         ns = (control >> 1) & MMASK;
  108.     case S: /* Note fall-thru */
  109. #ifdef __GNUC__
  110.     default:        /* shuts off warning about nr */
  111. #endif
  112.         nr = (control >> 5) & MMASK;
  113.         break;
  114.     }
  115.     /* This section follows the SDL diagrams by K3NA fairly closely */
  116.     switch(axp->state){
  117.     case LAPB_DISCONNECTED:
  118.         switch(type){
  119.         case SABM:      /* Initialize or reset link */
  120.         /* This a new incoming connection.
  121.          * Accept if we have enough memory left
  122.          * 920115 - WG7J
  123.          */
  124. #ifndef UNIX
  125.         if(availmem() < Memthresh){
  126.         sendctl(axp,LAPB_RESPONSE,DM|pf);
  127.         break;
  128.         }
  129. #endif
  130.         sendctl(axp,LAPB_RESPONSE,UA|pf);   /* Always accept */
  131.             clr_ex(axp);
  132.             axp->unack = axp->vr = axp->vs = 0;
  133.             lapbstate(axp,LAPB_CONNECTED);/* Resets state counters */
  134.             axp->srt = Axirtt;
  135.             axp->mdev = 0;
  136.             set_timer(&axp->t1,2*axp->srt);
  137.             start_timer(&axp->t3);
  138.             start_timer(&axp->t4);
  139. #ifdef SABM_HOLDOFF
  140.         axp->flags.rxd_I_frame = 0;    /* nothing received yet */
  141. #endif
  142.         /*Jump-start the mailbox. This causes the [NET-H$] prompt to
  143.          *be sent Immediately, instead of after the first data packet
  144.              *Check for connections from known netrom calls,
  145.              *calls from the 'jumpstart exclude' list and check if interface
  146.              *is in vc mode...
  147.              *we don't want to start the mailbox in these cases,
  148.              *since these could be attempts to do level 3 stuff.
  149.          *12/09/91 WG7J
  150.          */
  151. #ifdef MAILBOX
  152.         if(Mbjumpstart) {
  153. #ifdef NETROM
  154.         if(axp->jumpstarted == NETROM_LINK) {
  155.             /* check if the incoming interface is enabled for netrom*/
  156.             if(axp->iface->flags & IS_NR_IFACE)
  157.             if(find_nrnbr(axp->remote,axp->iface) != NULLNTAB)
  158.                 /* this is a netrom neighbour*/
  159.                 break;
  160.         }
  161. #endif /* NETROM */
  162.                 /*Now check the 'exclude' list*/
  163.                 for(ep=Exclude;ep!=(struct no_js *)NULL;ep=ep->next)
  164.                     if(addreq(axp->remote,ep->call))
  165.                         break;
  166.                 if(ep != (struct no_js *)NULL) /*exclude this one*/
  167.                     break;
  168.  
  169.         /*if the interface mode = VC, then DO NOT do it,
  170.          * this could be a VC attempted by IP!
  171.          */
  172.         if(!(axp->iface->flags & CONNECT_MODE)) {
  173.                     /*We passed all tests!*/
  174.             axp->jumpstarted += JUMPSTARTED;
  175.                     s_arcall(axp,0);
  176.                 }
  177.         }
  178. #endif /* MAILBOX */
  179.         break;
  180.         case DISC:      /* Always answer a DISC with a DM */
  181.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  182.             break;
  183.         case DM:        /* Ignore to avoid infinite loops */
  184.             break;
  185.         default:        /* All others get DM */
  186.             if(poll)
  187.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  188.             break;
  189.         }
  190.         if(axp->state == LAPB_DISCONNECTED){    /* we can close connection */
  191.             stop_timer(&axp->t1);   /* waste all the timers */
  192.             stop_timer(&axp->t3);
  193.             stop_timer(&axp->t4);
  194.             free_q(&axp->txq);      /* lose transmit queue */
  195.             drop_axr(axp);          /* drop ax25 route */
  196.             del_ax25(axp);      /* clean out the trash */
  197.             free_p(bp);
  198.             return 0;
  199.         }
  200.         break;
  201.     case LAPB_SETUP:
  202.         switch(type){
  203.         case SABM:      /* Simultaneous open */
  204.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  205.             break;
  206.         case DISC:
  207.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  208. #ifdef NETROM
  209.             nr_derate(axp);
  210. #endif
  211.             drop_axr(axp);      /* drop ax25 route */
  212.             free_q(&axp->txq);
  213.             stop_timer(&axp->t1);
  214.             axp->reason = LB_DM;
  215.             lapbstate(axp,LAPB_DISCONNECTED);
  216.             free_p(bp);
  217.             return 0;
  218. /*            break;    */
  219.         case UA:        /* Connection accepted */
  220.             /* Note: xmit queue not cleared */
  221.             stop_timer(&axp->t1);
  222.             start_timer(&axp->t3);
  223.             axp->unack = axp->vr = axp->vs = 0;
  224.             lapbstate(axp,LAPB_CONNECTED);
  225.             start_timer(&axp->t4);
  226.             break;
  227.         case DM:        /* Connection refused */
  228.             free_q(&axp->txq);
  229.             stop_timer(&axp->t1);
  230.             axp->reason = LB_DM;
  231.             lapbstate(axp,LAPB_DISCONNECTED);
  232.             free_p(bp);
  233.             return 0;
  234. /*            break;    */
  235.         default:        /* Respond with DM only to command polls */
  236.             if(poll)
  237.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  238.             break;
  239.         }
  240.         break;
  241.     case LAPB_DISCPENDING:
  242.         switch(type){
  243.         case SABM:
  244.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  245.             drop_axr(axp);          /* drop ax25 route */
  246.         break;
  247.         case DISC:
  248.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  249.             drop_axr(axp);          /* drop ax25 route */
  250.         break;
  251.         case UA:
  252.         case DM:
  253.             stop_timer(&axp->t1);
  254.             lapbstate(axp,LAPB_DISCONNECTED);
  255.             free_p(bp);
  256.             return 0;
  257. /*             break; */
  258.         default:        /* Respond with DM only to command polls */
  259.             if(poll)
  260.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  261.             drop_axr(axp);          /* drop ax25 route */
  262.         break;
  263.         }
  264.         break;
  265.     case LAPB_CONNECTED:
  266.         switch(type){
  267.         case SABM:
  268.        sendctl(axp,LAPB_RESPONSE,UA|pf);
  269. #ifdef SABM_HOLDOFF
  270.        if (axp->flags.rxd_I_frame) {
  271.         /* only reset if we've had a */
  272.         /* valid I-frame. Otherwise he */
  273.         /* may just not have got our UA */
  274. #endif
  275.         clr_ex(axp);
  276.         free_q(&axp->txq);
  277.         stop_timer(&axp->t1);
  278.         start_timer(&axp->t3);
  279.         axp->unack = axp->vr = axp->vs = 0;
  280.         lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  281. #ifdef SABM_HOLDOFF
  282.         }
  283. #endif
  284.         break;
  285.         case DISC:
  286.             free_q(&axp->txq);
  287.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  288.             stop_timer(&axp->t1);
  289.             stop_timer(&axp->t3);
  290.             axp->reason = LB_NORMAL;
  291.             lapbstate(axp,LAPB_DISCONNECTED);
  292.             free_p(bp);
  293.             return 0;
  294. /*            break;    */
  295.         case DM:
  296.             axp->reason = LB_DM;
  297.             lapbstate(axp,LAPB_DISCONNECTED);
  298.             free_p(bp);
  299.             return 0;
  300. /*            break;    */
  301.         case UA:
  302.             est_link(axp);
  303.             lapbstate(axp,LAPB_SETUP);      /* Re-establish */      
  304.             break;                  
  305.         case FRMR:
  306.             est_link(axp);
  307.             lapbstate(axp,LAPB_SETUP);      /* Re-establish link */
  308.             break;
  309.         case RR:
  310.         case RNR:
  311.             /* ve3dte@gw.ve3rpi.ampr.org: "control" isn't right */
  312.             axp->flags.remotebusy = (type == RNR) ? YES : NO;
  313.             if(poll)
  314.                 enq_resp(axp);
  315.             ackours(axp,nr);
  316.             break;
  317.         case REJ:
  318.             axp->flags.remotebusy = NO;
  319.             if(poll)
  320.                 enq_resp(axp);
  321.             ackours(axp,nr);
  322.             stop_timer(&axp->t1);
  323.             start_timer(&axp->t3);
  324.             /* This may or may not actually invoke transmission,
  325.              * depending on whether this REJ was caused by
  326.              * our losing his prior ACK.
  327.              */
  328.             inv_rex(axp);
  329.             break;  
  330.         case I:
  331.             ackours(axp,nr); /** == -1) */
  332. #ifdef SABM_HOLDOFF
  333.         axp->flags.rxd_I_frame = 1;   /* we got something */
  334. #endif
  335.         start_timer(&axp->t4);
  336.             if(len_p(axp->rxq) >= axp->window){
  337.                 /* Too bad he didn't listen to us; he'll
  338.                  * have to resend the frame later. This
  339.                  * drastic action is necessary to avoid
  340.                  * deadlock.
  341.                  */
  342.                 if(poll)
  343.                     sendctl(axp,LAPB_RESPONSE,RNR|pf);
  344.                 free_p(bp);
  345.                 bp = NULLBUF;
  346.                 break;
  347.             }
  348.             /* Reject or ignore I-frames with receive sequence number errors */
  349.             if(ns != (unsigned)axp->vr){
  350.                 if(axp->proto == V1 || !axp->flags.rejsent){
  351.                     axp->flags.rejsent = YES;
  352.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  353.                 } else if(poll)
  354.                     enq_resp(axp);
  355.                 axp->response = 0;
  356.                 break;
  357.             }
  358.             axp->flags.rejsent = NO;
  359.             axp->vr = (axp->vr+1) & MMASK;
  360.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  361.             if(poll){
  362.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  363.             } else {
  364.                 axp->response = tmp;
  365.             }
  366.             procdata(axp,bp);
  367.             bp = NULLBUF;
  368.             break;
  369.         default:        /* All others ignored */
  370.             break;
  371.         }
  372.         break;
  373.     case LAPB_RECOVERY:
  374.         switch(type){
  375.         case SABM:
  376.         sendctl(axp,LAPB_RESPONSE,UA|pf);
  377. #ifdef SABM_HOLDOFF
  378.        if (axp->flags.rxd_I_frame) {
  379.         /* only reset if we've had a */
  380.         /* valid I-frame. Otherwise he */
  381.         /* may just not have got our UA */
  382. #endif
  383.         clr_ex(axp);
  384.         stop_timer(&axp->t1);
  385.         start_timer(&axp->t3);
  386.         axp->unack = axp->vr = axp->vs = 0;
  387.         lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  388.         if(!run_timer(&axp->t4))
  389.             start_timer(&axp->t4);
  390. #ifdef SABM_HOLDOFF
  391.         }
  392. #endif
  393.         break;
  394.         case DISC:
  395.             free_q(&axp->txq);
  396.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  397.             stop_timer(&axp->t1);
  398.             stop_timer(&axp->t3);
  399.             axp->response = UA;
  400.             axp->reason = LB_NORMAL;
  401.             lapbstate(axp,LAPB_DISCONNECTED);
  402.             free_p(bp);
  403.             return 0;
  404. /*            break;    */
  405.         case DM:
  406. #ifdef NETROM
  407.         nr_derate(axp);
  408. #endif
  409.         axp->reason = LB_DM;
  410.             lapbstate(axp,LAPB_DISCONNECTED);
  411.             free_p(bp);
  412.             return 0;
  413. /*            break;    */
  414.         case UA:
  415.             est_link(axp);
  416.             lapbstate(axp,LAPB_SETUP);      /* Re-establish */      
  417.             break;
  418.         case FRMR:
  419.             est_link(axp);
  420.             lapbstate(axp,LAPB_SETUP);      /* Re-establish link */
  421.             break;
  422.         case RR:
  423.         case RNR:
  424.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  425.             if(axp->proto == V1 || final){
  426.                 stop_timer(&axp->t1);
  427.                 ackours(axp,nr);
  428.                 if(axp->unack != 0){
  429.                     inv_rex(axp);
  430.                 } else {
  431.                     start_timer(&axp->t3);
  432.                     lapbstate(axp,LAPB_CONNECTED);
  433.                     if(!run_timer(&axp->t4))
  434.                         start_timer(&axp->t4);
  435.                 }
  436.             } else {
  437.                 if(poll)
  438.                     enq_resp(axp);
  439.                 ackours(axp,nr);
  440.                 /* Keep timer running even if all frames
  441.                  * were acked, since we must see a Final
  442.                  */
  443.                 if(!run_timer(&axp->t1))
  444.                     start_timer(&axp->t1);
  445.             }
  446.             break;
  447.         case REJ:
  448.             axp->flags.remotebusy = NO;
  449.             /* Don't insist on a Final response from the old proto */
  450.             if(axp->proto == V1 || final){
  451.                 stop_timer(&axp->t1);
  452.                 ackours(axp,nr);
  453.                 if(axp->unack != 0){
  454.                     inv_rex(axp);
  455.                 } else {
  456.                     start_timer(&axp->t3);
  457.                     lapbstate(axp,LAPB_CONNECTED);
  458.                     if(!run_timer(&axp->t4))
  459.                         start_timer(&axp->t4);
  460.                 }
  461.             } else {
  462.                 if(poll)
  463.                     enq_resp(axp);
  464.                 ackours(axp,nr);
  465.                 if(axp->unack != 0){
  466.                     /* This is certain to trigger output */
  467.                     inv_rex(axp);
  468.                 }
  469.                 /* A REJ that acks everything but doesn't
  470.                  * have the F bit set can cause a deadlock.
  471.                  * So make sure the timer is running.
  472.                  */
  473.                 if(!run_timer(&axp->t1))
  474.                     start_timer(&axp->t1);
  475.             }
  476.             break;
  477.         case I:
  478.             ackours(axp,nr); /** == -1) */
  479. #ifdef SABM_HOLDOFF
  480.         axp->flags.rxd_I_frame = YES;   /* we got something */
  481. #endif
  482.         /* Make sure timer is running, since an I frame
  483.              * cannot satisfy a poll
  484.              */
  485.             if(!run_timer(&axp->t1))
  486.                 start_timer(&axp->t1);
  487.             if(len_p(axp->rxq) >= axp->window){
  488.                 /* Too bad he didn't listen to us; he'll
  489.                  * have to resend the frame later. This
  490.                  * drastic action is necessary to avoid
  491.                  * memory deadlock.
  492.                  */
  493.                 sendctl(axp,LAPB_RESPONSE,RNR | pf);
  494.                 free_p(bp);
  495.                 bp = NULLBUF;
  496.                 break;
  497.             }
  498.             /* Reject or ignore I-frames with receive sequence number errors */
  499.             if(ns != (unsigned)axp->vr){
  500.                 if(axp->proto == V1 || !axp->flags.rejsent){
  501.                     axp->flags.rejsent = YES;
  502.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  503.                 } else if(poll)
  504.                     enq_resp(axp);
  505.  
  506.                 axp->response = 0;
  507.                 break;
  508.             }
  509.             axp->flags.rejsent = NO;
  510.             axp->vr = (axp->vr+1) & MMASK;
  511.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  512.             if(poll){
  513.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  514.             } else {
  515.                 axp->response = tmp;
  516.             }
  517.             procdata(axp,bp);
  518.             bp = NULLBUF;
  519.             break;
  520.         default:
  521.             break;          /* Ignored */
  522.         }
  523.         break;
  524.     }
  525.     free_p(bp);     /* In case anything's left */
  526.  
  527.     /* See if we can send some data, perhaps piggybacking an ack.
  528.      * If successful, lapb_output will clear axp->response.
  529.      */
  530.     lapb_output(axp);
  531.     if(axp->response != 0){
  532.         sendctl(axp,LAPB_RESPONSE,axp->response);
  533.         axp->response = 0;
  534.     }
  535.     return 0;
  536. }
  537.  
  538. /* Handle incoming acknowledgements for frames we've sent.
  539.  * Free frames being acknowledged.
  540.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  541.  */
  542. static int
  543. ackours(axp,n)
  544. struct ax25_cb *axp;
  545. int16 n;
  546. {       
  547.     struct mbuf *bp;
  548.     int acked = 0;  /* Count of frames acked by this ACK */
  549.     int16 oldest;   /* Seq number of oldest unacked I-frame */
  550.     int32 rtt,abserr;
  551.  
  552.     /* Free up acknowledged frames by purging frames from the I-frame
  553.      * transmit queue. Start at the remote end's last reported V(r)
  554.      * and keep going until we reach the new sequence number.
  555.      * If we try to free a null pointer,
  556.      * then we have a frame reject condition.
  557.      */
  558.     oldest = (axp->vs - axp->unack) & MMASK;
  559.     while(axp->unack != 0 && oldest != n){
  560.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  561.             /* Acking unsent frame */
  562.             return -1;
  563.         }
  564.         free_p(bp);
  565.         axp->unack--;
  566.         acked++;
  567.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  568.             /* A frame being timed has been acked */
  569.             axp->flags.rtt_run = 0;
  570.             /* Update only if frame wasn't retransmitted */
  571.             if(!axp->flags.retrans){
  572.                 rtt = msclock() - axp->rtt_time;
  573.                 abserr = (rtt > axp->srt) ? rtt - axp->srt :
  574.                  axp->srt - rtt;
  575.  
  576.                 /* Run SRT and mdev integrators */
  577.                 axp->srt = ((axp->srt * 7) + rtt + 4) >> 3;
  578.                 axp->mdev = ((axp->mdev*3) + abserr + 2) >> 2;
  579.                 /* Update timeout */
  580.                 set_timer(&axp->t1,4*axp->mdev+axp->srt);
  581.             }
  582.         }
  583.         axp->flags.retrans = 0;
  584.         axp->retries = 0;
  585.         oldest = (oldest + 1) & MMASK;
  586.     }
  587.     if(axp->unack == 0){
  588.         /* All frames acked, stop timeout */
  589.         stop_timer(&axp->t1);
  590.         start_timer(&axp->t3);
  591.     } else if(acked != 0) { 
  592.         /* Partial ACK; restart timer */
  593.         start_timer(&axp->t1);
  594.     }
  595.     if(acked != 0){
  596.         /* If user has set a transmit upcall, indicate how many frames
  597.          * may be queued
  598.          */
  599.         if(axp->t_upcall != NULLVFP((struct ax25_cb*,int)))
  600.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  601.     }
  602.     return 0;
  603. }
  604.  
  605. /* Establish data link */
  606. void
  607. est_link(axp)
  608. struct ax25_cb *axp;
  609. {
  610.     clr_ex(axp);
  611.     axp->retries = 0;
  612.     sendctl(axp,LAPB_COMMAND,SABM|PF);
  613.     stop_timer(&axp->t3);
  614.     start_timer(&axp->t1);
  615. }
  616. /* Clear exception conditions */
  617. static void
  618. clr_ex(axp)
  619. struct ax25_cb *axp;
  620. {
  621.     axp->flags.remotebusy = NO;
  622.     axp->flags.rejsent = NO;
  623.     axp->response = 0;
  624.     stop_timer(&axp->t3);
  625. }
  626. /* Enquiry response */
  627. static void
  628. enq_resp(axp)
  629. struct ax25_cb *axp;
  630. {
  631.     char ctl;
  632.  
  633.     ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;  
  634.     sendctl(axp,LAPB_RESPONSE,ctl);
  635.     axp->response = 0;
  636.     stop_timer(&axp->t3);
  637. }
  638. /* Invoke retransmission */
  639. static void
  640. inv_rex(axp)
  641. struct ax25_cb *axp;
  642. {
  643.     axp->vs -= axp->unack;
  644.     axp->vs &= MMASK;
  645.     axp->unack = 0;
  646. }
  647. /* Send S or U frame to currently connected station */
  648. int
  649. sendctl(axp,cmdrsp,cmd)
  650. struct ax25_cb *axp;
  651. int cmdrsp;
  652. int cmd;
  653. {
  654.     if((ftype((char)cmd) & 0x3) == S)       /* Insert V(R) if S frame */
  655.         cmd |= (axp->vr << 5);
  656.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  657. }
  658. /* Start data transmission on link, if possible
  659.  * Return number of frames sent
  660.  */
  661. int
  662. lapb_output(axp)
  663. register struct ax25_cb *axp;
  664. {
  665.     register struct mbuf *bp;
  666.     struct mbuf *tbp;
  667.     char control;
  668.     int sent = 0;
  669.     int i;
  670.  
  671.     if(axp == NULLAX25
  672.      || (axp->state != LAPB_RECOVERY && axp->state != LAPB_CONNECTED)
  673.      || axp->flags.remotebusy)
  674.         return 0;
  675.  
  676.     /* Dig into the send queue for the first unsent frame */
  677.     bp = axp->txq;
  678.     for(i = 0; i < axp->unack; i++){
  679.         if(bp == NULLBUF)
  680.             break;  /* Nothing to do */
  681.         bp = bp->anext;
  682.     }
  683.     /* Start at first unsent I-frame, stop when either the
  684.      * number of unacknowledged frames reaches the maxframe limit,
  685.      * or when there are no more frames to send
  686.      */
  687.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  688.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  689.         axp->vs &= MMASK;
  690.         dup_p(&tbp,bp,0,len_p(bp));
  691.         if(tbp == NULLBUF)
  692.             return sent;    /* Probably out of memory */
  693.         sendframe(axp,LAPB_COMMAND,control,tbp);
  694.         start_timer(&axp->t4);
  695.         axp->unack++;
  696.         /* We're implicitly acking any data he's sent, so stop any
  697.          * delayed ack
  698.          */
  699.         axp->response = 0;
  700.         if(!run_timer(&axp->t1)){
  701.             stop_timer(&axp->t3);
  702.             start_timer(&axp->t1);
  703.         }
  704.         sent++;
  705.         bp = bp->anext;
  706.         if(!axp->flags.rtt_run){
  707.             /* Start round trip timer */
  708.             axp->rtt_seq = (control >> 1) & MMASK;
  709.             axp->rtt_time = msclock();
  710.             axp->flags.rtt_run = 1;
  711.         }
  712.     }
  713.     return sent;
  714. }
  715. /* Set new link state */
  716. void
  717. lapbstate(axp,s)
  718. struct ax25_cb *axp;
  719. int s;
  720. {
  721.     int oldstate;
  722.  
  723.     oldstate = axp->state;
  724.     axp->state = s;
  725.     if(s == LAPB_DISCONNECTED){
  726.         stop_timer(&axp->t1);
  727.         stop_timer(&axp->t3);
  728.         stop_timer(&axp->t4);
  729.         free_q(&axp->txq);
  730.         drop_axr(axp);          /* any ax25 route that hasn't been dropped yet*/
  731.     }
  732.     /* Don't bother the client unless the state is really changing */
  733.     if((oldstate != s) && (axp->s_upcall != NULLVFP((struct ax25_cb*,int,int))))
  734.         (*axp->s_upcall)(axp,oldstate,s);
  735. }
  736. /* Process a valid incoming I frame */
  737. static void
  738. procdata(axp,bp)
  739. struct ax25_cb *axp;
  740. struct mbuf *bp;
  741. {
  742.     int pid;
  743.     int seq;
  744.  
  745.     /* Extract level 3 PID */
  746.     if((pid = PULLCHAR(&bp)) == -1)
  747.         return; /* No PID */
  748.  
  749.     if(axp->segremain != 0){
  750.         /* Reassembly in progress; continue */
  751.         seq = PULLCHAR(&bp);
  752.         if(pid == PID_SEGMENT
  753.          && (seq & SEG_REM) == axp->segremain - 1){
  754.             /* Correct, in-order segment */
  755.             append(&axp->rxasm,bp);
  756.             if((axp->segremain = (seq & SEG_REM)) == 0){
  757.                 /* Done; kick it upstairs */
  758.                 bp = axp->rxasm;
  759.                 axp->rxasm = NULLBUF;
  760.                 pid = PULLCHAR(&bp);
  761.                 handleit(axp,pid,bp);
  762.             }
  763.         } else {
  764.             /* Error! */
  765.             free_p(axp->rxasm);
  766.             axp->rxasm = NULLBUF;
  767.             axp->segremain = 0;
  768.             free_p(bp);
  769.         }
  770.     } else {
  771.         /* No reassembly in progress */
  772.         if(pid == PID_SEGMENT){
  773.             /* Start reassembly */
  774.             seq = PULLCHAR(&bp);
  775.             if(!(seq & SEG_FIRST)){
  776.                 free_p(bp);     /* not first seg - error! */
  777.             } else {
  778.                 /* Put first segment on list */
  779.                 axp->segremain = seq & SEG_REM;
  780.                 axp->rxasm = bp;
  781.             }
  782.         } else {
  783.             /* Normal frame; send upstairs */
  784.             handleit(axp,pid,bp);
  785.         }
  786.     }
  787. }
  788. /* New-style frame segmenter. Returns queue of segmented fragments, or
  789.  * original packet if small enough
  790.  */
  791. struct mbuf *
  792. segmenter(bp,ssize)
  793. struct mbuf *bp;        /* Complete packet */
  794. int16 ssize;            /* Max size of frame segments */
  795. {
  796.     struct mbuf *result = NULLBUF;
  797.     struct mbuf *bptmp,*bp1;
  798.     int16 len,offset;
  799.     int segments;
  800.  
  801.     /* See if packet is too small to segment. Note 1-byte grace factor
  802.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  803.      */
  804.     len = len_p(bp);
  805.     if(len <= ssize+1)
  806.         return bp;      /* Too small to segment */
  807.  
  808.     ssize -= 2;             /* ssize now equal to data portion size */
  809.     segments = 1 + (len - 1) / ssize;       /* # segments  */
  810.     offset = 0;
  811.  
  812.     while(segments != 0){
  813.         offset += dup_p(&bptmp,bp,offset,ssize);
  814.         if(bptmp == NULLBUF){
  815.             free_q(&result);
  816.             break;
  817.         }
  818.         /* Make room for segmentation header */
  819.         if((bp1 = pushdown(bptmp,2)) == NULLBUF){
  820.             free_p(bptmp);
  821.             free_q(&result);
  822.             break;
  823.         }
  824.         bp1->data[0] = PID_SEGMENT;
  825.         bp1->data[1] = --segments;
  826.         if(offset == ssize)
  827.             bp1->data[1] |= SEG_FIRST;
  828.         enqueue(&result,bp1);
  829.     }
  830.     free_p(bp);
  831.     return result;
  832. }
  833.  
  834. static void
  835. handleit(axp,pid,bp)
  836. struct ax25_cb *axp;
  837. int pid;
  838. struct mbuf *bp;
  839. {
  840.     struct axlink *ipp;
  841.  
  842.     for(ipp = Axlink;ipp->funct != NULL;ipp++){
  843.         if(ipp->pid == pid)
  844.             break;
  845.     }
  846.     if(ipp->funct != NULL)
  847.         (*ipp->funct)(axp->iface,axp,NULLCHAR,NULLCHAR,bp,0);
  848.     else
  849.         free_p(bp);
  850. }
  851.  
  852. #endif /* AX25 */
  853.  
  854.